package org.batatasframework.immadiate;

import java.util.Date;
import java.util.List;

import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletResponse;

import org.batatasframework.common.ParameterReader;
import org.batatasframework.support.AbstractSupportHandler;
import org.springframework.ui.Model;
import org.springframework.util.Assert;

import cn.bonoon.entities.ImmediatePlanEntity;
import cn.bonoon.entities.ImmediateTaskEntity;
import cn.bonoon.entities.ImmediateTaskMaterial;
import cn.bonoon.entities.ImmediateTaskMaterialLog;
import cn.bonoon.entities.ImmediateTaskStatus;
import cn.bonoon.entities.ImmediateTaskStatusLog;
import cn.bonoon.entities.ImmediateTaskType;
import cn.bonoon.kernel.io.FileManager;
import cn.bonoon.kernel.support.IOperator;

public class ImmadiateScheduleHandler extends AbstractSupportHandler<ImmadiatePlanDefinition> {
//	private final Logger log =  LoggerFactory.getLogger(this.getClass());

//	private @PersistenceContext EntityManager entityManager;
//	private @Autowired FileManager fileManager;
//	private ApplicationContext applicationContext;
//	
//	private ImmadiatePlanRegister[] registers;

//	private final CatalogDefinitionMapped<RawdataDefinition> catalogMapped = new CatalogDefinitionMapped<>();
	
//	private final Map<String, ImmadiatePlanDefinition> planDefinitions = new HashMap<>();
//	
//	private class CatalogImmadiateScheduleCollection{
//		final String catalog;
//		final Map<String, ImmadiatePlanDefinition> definitionMapped = new HashMap<>();
//	}
//	protected DefinitionBuilder<ImmadiatePlanDefinition> generateBuilder() {
//		return new InternalImmadiatePlanBuilder();
//	}
//	private class InternalImmadiatePlanBuilder implements DefinitionBuilder<ImmadiatePlanDefinition>{
//		
//		/** 当前正在处理的定义 */
//		private ImmadiatePlanDefinition currentDefinition;
//
//		private String catalog;
//		@Override
//		public ImmadiatePlanDefinition add(String key, String name/*, String vmpath*/) {
//			
//			currentDefinition = new ImmadiatePlanDefinition(key, name/*, vmpath*/);
////			Assert.isNull(planDefinitions.put(key, planDefinition), 
////					"已经存在[" + key + "]的定义！");
//			catalogMapped.put(catalog, key, currentDefinition);
//			log.info("新增加定义：" + currentDefinition);
//			return currentDefinition;
//		}
//
////		@Override
////		public void handler(ImmediateTaskHandler<? extends ImmediateTaskEntity> handler) {
////			handler.initialize(/*entityManager, */fileManager, currentDefinition);
////			currentDefinition.setHandler(handler);
////		}
//
//		@Override
//		public void addGroup(String catalog) {
//			this.catalog = catalog;
//		}
//		
//	};
//	@Override
//	public void afterPropertiesSet() throws Exception {
//		if(null != registers){
//			for(ImmadiatePlanRegister register : registers){
//				register.register(builder);
//			}
//		}
//
//	}

//	@Override
//	public void setApplicationContext(ApplicationContext context)
//			throws BeansException {
//		applicationContext = context;
//
//	}
//
//	public void setRegisters(ImmadiatePlanRegister[] registers) {
//		this.registers = registers;
//
//	}

	protected ImmadiatePlanDefinition generateDefinition(String key, String name) {
		return new ImmadiatePlanDefinition(key, name);
	}
	
//	@Override
	public ImmediateTaskInfo myTask(EntityManager entityManager, IOperator user,
			List<ImmediateTaskInfo> tasks) {
		String ql = "select x from ImmediateTaskEntity x where x.plan.deleted=false";
		ql += " and x.plan.expireAt>?";
		ql += " and x.plan.startAt<?";
		
		ql += " and ((x.type=? and executor=?) or (x.type=? and executor=?))";
		
		Date now = new Date();
		TypedQuery<ImmediateTaskEntity> tqSelect = entityManager.createQuery(ql, ImmediateTaskEntity.class);
		tqSelect.setParameter(1, now);
		tqSelect.setParameter(2, now);
		
		tqSelect.setParameter(3, ImmediateTaskType.OWNER);
		tqSelect.setParameter(4, user.getOwnerId());
		tqSelect.setParameter(5, ImmediateTaskType.PERSONAL);
		tqSelect.setParameter(6, user.getId());
		
		ImmediateTaskInfo unacceptedTask = null;
		for(ImmediateTaskEntity ite : tqSelect.getResultList()){
			ImmediateTaskInfo iti = new ImmediateTaskInfo(ite);
			tasks.add(iti);
			if(null == unacceptedTask && ite.getStatus() == ImmediateTaskStatus.UNACCEPTED){
				unacceptedTask = iti;
			}
		}
		return unacceptedTask;
	}

//	@Override
	public ImmediateTaskHandler<? extends ImmediateTaskEntity> findTaskHandler(String catalog, String key) {
		return __findTaskHandler(catalog, key);
	}

//	@Override
	public ImmadiatePlanDefinition findDefinition(String catalog, String key) {
		return catalogMapped.notNull(catalog, key, "找不到任务[key:" + key + "]的定义！");
//		Assert.hasText(key, "[key]参数不能为空！");
//		ImmadiatePlanDefinition definition = planDefinitions.get(key);
//		Assert.notNull(definition, "找不到任务[key:" + key + "]的定义！");
//		return definition; 
	}

	private ImmediateTaskHandler<? extends ImmediateTaskEntity> __findTaskHandler(String catalog, String key) {
		return catalogMapped.notNull(catalog, key, "找不到任务[key:" + key + "]的定义！").getHandler();
//		Assert.hasText(key, "[key]参数不能为空！");
//		ImmadiatePlanDefinition definition = planDefinitions.get(key);
//		Assert.notNull(definition, "找不到任务[key:" + key + "]的定义！");
//		return definition.getHandler(); 
	}
	
//	@Override
	public void export(IOperator user, String catalog, String key, ParameterReader parameter,
			HttpServletResponse response,ServletContext servletContext, EntityManager entityManager) {
		ImmediateTaskHandler<? extends ImmediateTaskEntity> taskHandler = __findTaskHandler(catalog, key);
		taskHandler.export(user, parameter, response, servletContext, entityManager);
	}

//	@Override
	public void deleteMaterial(String catalog, String key, EntityManager entityManager,IOperator user, Long taskid, Long id) {
		ImmediateTaskMaterial material = entityManager.find(ImmediateTaskMaterial.class, id);
		ImmediateTaskEntity task = material.getTask();
		Assert.isTrue(taskid.equals(task.getId()), "需要被删除的材料与任务不一致！");
		
		Date now = new Date();
		checkEditable(key, user, task, now);
		
		//检查通过
		material.setDeleted(true);
		entityManager.merge(material);
		ImmediateTaskMaterialLog taskLog = new ImmediateTaskMaterialLog();
		taskLog.setContent("[删除文件]" + material.getName());
		taskLog.setSource(task);
		taskLog.setMaterial(material);
		taskLog.setCreateAt(now);
		taskLog.operator(user);
		
		entityManager.persist(taskLog);

	}

	
	public static void checkEditable(String key, IOperator user, ImmediateTaskEntity task, Date now) {
		Assert.isTrue(task.getStatus().editable(), "任务不是正在执行的状态！");
		long executor = task.getExecutor();
		ImmediateTaskType type = task.getType();
		if(type == ImmediateTaskType.OWNER){
			Assert.isTrue(user.toOwnerId() == executor, "不允许改动非自己部门/单位的数据！");
		}else if(type == ImmediateTaskType.PERSONAL){
			Assert.isTrue(user.getId() == executor, "不允许改动非自己的数据！");
		}
		
		ImmediatePlanEntity plan = task.getPlan();
		Assert.isTrue(key.equals(plan.getKey()), "任务编码不正确！");
		Assert.isTrue(now.before(task.getEndAt()), "任务已经结束！");
		Assert.isTrue(now.before(plan.getExpireAt()), "任务已经过期！");

	}

//	@Override
	public void update(String catalog, String key, EntityManager entityManager, FileManager fileManager, IOperator user, ParameterReader parameter)
			throws Exception {
		ImmediateTaskHandler<? extends ImmediateTaskEntity> taskHandler = __findTaskHandler(catalog, key);
		taskHandler.update(entityManager, fileManager, user, parameter);

	}

//	@Override
	public void accepted(EntityManager entityManager,IOperator operator, ImmediateTaskEntity task) {
		if(task.getStatus() == ImmediateTaskStatus.UNACCEPTED){
			ImmediateTaskStatus targetStatus = ImmediateTaskStatus.STARTED;
			
			ImmediateTaskStatusLog log = new ImmediateTaskStatusLog();
			log.setContent("[接受任务]");
			log.setCreateAt(new Date());
			log.setFromStatus(task.getStatus());
			log.setToStatus(targetStatus);
			log.setSource(task);
			log.operator(operator);
			
			task.setStatus(targetStatus);
			
			entityManager.merge(task);
			entityManager.persist(log);
		}

	}

//	@Override
	public ImmediateTaskEntity loadToShow(ImmadiatePlanDefinition def, EntityManager entityManager,IOperator user, ParameterReader parameter, Model model) {
		return def.getHandler().loadToShow(user, entityManager, parameter, model);
	}

}
